package droid.mapViewer.primitives;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader; 
import java.util.ArrayList;
import java.util.List;

import droid.mapViewer.exceptions.InvalidFileFormatException;
import droid.mapViewer.graphDrawers.Brush;
import droid.mapViewer.graphDrawers.Pen;
import droid.mapViewer.utils.Center;
import droid.mapViewer.utils.Point;

public class PrimitiveFactory {
	private static final int LINE_PARAM_COUNT = 5; //Количество параметров в строке Line
	private static final int PLINE_PARAM_COUNT = 2; //Количество параметров в строке PLine
	private static final int REGION_PARAM_COUNT = 3; //Количество параметров в строке Region (2 пробела почему-то...)
	private List<IPrimitive> primitives;
	
	private String sep = ",";	//Разделитель в файле MIF 
	
	public PrimitiveFactory(String fName) throws  IOException, InvalidFileFormatException {
		BufferedReader in = openFile(fName);
        String str;
        String[] strs;
        primitives = new ArrayList<IPrimitive>();
        List<Point> points = new ArrayList<Point>();
        while ((str = in.readLine()) != null) {
        	strs = str.split(" ");
        	if (strs.length > 0) {
	        	if (strs[0].equalsIgnoreCase("line")) {
	    			if (strs.length == LINE_PARAM_COUNT) {
	    				try {
	    					points.add(new Point(Float.parseFloat(strs[1]), Float.parseFloat(strs[2])));
	    					points.add(new Point(Float.parseFloat(strs[3]), Float.parseFloat(strs[4])));
	    					primitives.add(new PLine(points, new Pen(in.readLine(), sep)));
	    					points.clear();
	    				} catch (NumberFormatException e) {}	//С случае возникновения ошибки просто не добавляем эту линию
	    			}
	        	}
	        	else
	        	if (strs[0].equalsIgnoreCase("pline")) {
	        		if (strs.length == PLINE_PARAM_COUNT) {
	        			try {
	        				int pointsCount = Integer.parseInt(strs[1]); //Количество точек в полилинии
		        			for (int i=0; i<pointsCount; i++) {
		        				str = in.readLine();
		        				strs = str.split(" ");
		        				points.add(new Point(Float.parseFloat(strs[0]), Float.parseFloat(strs[1])));
		        			}
		        			primitives.add(new PLine(points, new Pen(in.readLine(), sep)));
	    					points.clear();	
	        			} catch (NumberFormatException e) {  
        					points.clear();	//В случае ошибки удаляем остатки полилинии
        				}
	        		}
	        	}
	        	else
	        	if (strs[0].equalsIgnoreCase("region")) {
	        		if (strs.length == REGION_PARAM_COUNT) {
	        			List<SimpleRegion> simpleRegions = new ArrayList<SimpleRegion>();
	        			try {
	        				int RegionsCount = Integer.parseInt(strs[2]);
	        				for (int i=0; i<RegionsCount; i++) { 
		        				int PointsCount = Integer.parseInt(in.readLine().trim());
		        				for (int j=0; j<PointsCount; j++) {
		        					str = in.readLine();
			        				strs = str.split(" ");
			        				points.add(new Point(Float.parseFloat(strs[0]), Float.parseFloat(strs[1])));
		        				}
		        				if (i !=RegionsCount-1) //В последний регион запишем Pen и Brush, т. к. они в файле MIF в конце
		        					simpleRegions.add(new SimpleRegion(points));
		        				else
		        					simpleRegions.add(new SimpleRegion(points,new Pen(in.readLine(), sep), new Brush(in.readLine(), sep),
		        																new Center(in.readLine()).getCenter()));
		        				//TODO Brush - заглушка, ничего не делает
	        				}
	        				primitives.add(new Region(simpleRegions));
	        				points.clear();
	        			}  catch (NumberFormatException e) {  
        					points.clear();	//В случае ошибки удаляем остатки полилинии
        				}
	        		}
	        	}
        	}
        }
        in.close();
	}
	
	public List<IPrimitive> getPrimitives() {
		return primitives;
	}
	
    private BufferedReader openFile(String fName) throws InvalidFileFormatException, IOException {
    	if (fName !=null && !fName.isEmpty()) {
			try {
				BufferedReader buffReader = new BufferedReader(new FileReader(new File(fName)));
				CheckFileHeader(buffReader);
				return buffReader;
		    } catch (FileNotFoundException e) {
		    	return null;
		    }
    	}
    	return null;
    }  
    
    /**
     * Метод проверяет формат файла. Если заголовок не соответствует формату, генерируется исключение <code>InvalidFileFormatException</code>
     * @throws InvalidFileFormatException
     * @throws IOException
     */
    private void CheckFileHeader(BufferedReader buffReader) throws InvalidFileFormatException, IOException {
    	String str = buffReader.readLine();
    	boolean verifiedOk = false;
    	if ((str != null) && (str.toLowerCase().startsWith("version"))) {
    		for (int i=0; i<6; i++) {
    			str = buffReader.readLine();
    			if (str != null) {
    				if (str.toLowerCase().startsWith("delimiter")) {
    					String[] strs = str.split(" ");
    					if (strs.length > 1) 
    						sep = strs[1].substring(1,strs[1].length()-1);
    					else throw new InvalidFileFormatException();
    				}
    				if (str.toLowerCase().startsWith("coordsys")) {} //TODO Задает размеры холста
    				if (str.toLowerCase().startsWith("transform")) {} //TODO Преобразует координаты
    				if (str.toLowerCase().startsWith("columns")) 
    					verifiedOk=true;
    			}
    			else throw new InvalidFileFormatException();
        	}
    		if (!verifiedOk) throw new InvalidFileFormatException();
    	}
    	else throw new InvalidFileFormatException();
    }
}
